package com.chy.blog_server.modular.map.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chy.blog_server.core.util.GetUserIpAddressUtil;
import com.chy.blog_server.core.util.StringUtil;
import com.chy.blog_server.modular.map.config.GdConfing;
import com.chy.blog_server.modular.map.entity.MapDistrict;
import com.chy.blog_server.modular.map.entity.MapLog;
import com.chy.blog_server.modular.map.entity.MapMerchantInfo;
import com.chy.blog_server.modular.map.mapper.MapMerchantInfoMapper;
import com.chy.blog_server.modular.map.service.IMapMerchantInfoService;
import com.fasterxml.jackson.databind.JsonNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description: 高德/百度地图获取商家信息 service业务层
 * @author: chenhuiyan
 * @create: 2025-03-22 15:22
 **/
@Service
@Transactional(readOnly = false)
public class MapMerchantInfoServiceImpl extends ServiceImpl<MapMerchantInfoMapper, MapMerchantInfo> implements IMapMerchantInfoService {

    private static final Logger logger = LoggerFactory.getLogger(MapMerchantInfoServiceImpl.class);

    @Autowired
    private MapDistrictServiceImpl mapDistrictService;

    @Autowired
    private MapLogServiceImpl mapLogService;

    /**
     * 查询列表
     * @param params
     * @return
     */
    public List<Map<String, Object>> list(Map<String, Object> params){
        chineseConvertMap(params); //省份/城市代码转中文
        return baseMapper.listPage(params);
    }

    /**
     * 查询列表-不分页
     * @param params
     * @return
     */
    public List<Map<String, Object>> listAll(Map<String, Object> params){
        return baseMapper.listAll(params);
    }

    /**
     * 查询列表-实体-不分页
     * @param params
     * @return
     */
    public List<MapMerchantInfo> listAllEntity(Map<String, Object> params){
        return baseMapper.listAllEntity(params);
    }

    /**
     * 查询已删除的列表
     * @param params
     * @return
     */
    public List<Map<String, Object>> recycleList(Map<String, Object> params){
        return baseMapper.recycleList(params);
    }

    /**
     * 彻底删除
     * @param id
     * @return
     */
    @Transactional(readOnly = false)
    public int thoroughlyDelete(String id){
        return baseMapper.thoroughlyDelete(id);
    }

    /**
     * 查询总数
     * @param params
     * @return
     */
    public int getCount(Map<String, Object> params){
        return baseMapper.getCount(params);
    }

    /**
     * 查询总数-分页使用
     * @param params
     * @return
     */
    public int getCountKeyword(Map<String, Object> params){
        chineseConvertMap(params); //省份/城市代码转中文
        return baseMapper.getCountKeyword(params);
    }

    /**
     * 获取商家信息
     * @param request
     * @param params
     * @return
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED) //不开启事务
    public List<Map<String, Object>> getMerchantInfo(HttpServletRequest request, Map<String, Object> params) throws Exception {
        String provinceCode = params.get("province") + ""; // 省份
        String cityCode = params.get("city") + ""; // 城市
//        String area = params.get("area") + "";  // 区/县
        String keyword = params.get("keyword") + ""; //搜索关键词
        String dataSource = params.get("dataSource") + ""; //数据来源
        String getType = params.get("getType") + ""; //抓取类型：1信息库中抓取，2重新抓取高徳
        String logCode = params.get("logCode") + ""; //日志编号
        String operateIp = GetUserIpAddressUtil.getIpAddress(request); //获取操作IP
        //获取省份和城市中文名称
        chineseConvertMap(params); //省份/城市代码转中文
        MapDistrict provinceDistrict = mapDistrictService.getOne(new QueryWrapper<MapDistrict>().eq("level", "province").eq("adcode", provinceCode));
        String province = provinceDistrict.getName(); // 省份中文名称
        String city = ""; // 城市中文名称
        if(provinceCode.equals(cityCode)){
            city = provinceDistrict.getName();
        }else{
            MapDistrict cityDistrict = mapDistrictService.getOne(new QueryWrapper<MapDistrict>().eq("level", "city").eq("adcode", cityCode));
            city = cityDistrict.getName();
        }
        String address = province + city;
        params.put("province", province);
        params.put("city", city);

        List<Map<String, Object>> list = new ArrayList<>();
        //先根据[目标城市]查询数据库是否存在数据，存在则取数据库，不存在则调用高德、百度接口获取并保存
        int count = getCount(params);
        if(count >= 1 && "1".equals(getType)){
            list = baseMapper.listAll(params);
        } else if("2".equals(getType)) {
            if("gaode".equals(dataSource)){ //调用高德API获取数据
                //获取区/县或者街道坐标
                List<Map<String, String>> locationList = mapDistrictService.getDistrictStreetCenterList(provinceCode, cityCode);
                String logText = "高德API接口调用>>>" + address + " 总共 " + locationList.size() + " 个位置信息";
                logger.info(logText);
                createGaodeLog(logCode, logText, province, city, keyword, operateIp); //生成日志
                List<MapMerchantInfo> poiList = new ArrayList<>();
                //重置KEY
                GdConfing.resetKey(mapLogService, operateIp, logCode, province, city, keyword);
                int i = 1;
                for(Map<String, String> locaMap: locationList){
                    String search_area = locaMap.get("name"); //搜索的坐标行政地区名称
                    String location = locaMap.get("center"); //坐标
                    logText = "高德API接口调用>>>正在执行第 " + i + " 个位置：" + city + search_area;
                    logger.info(logText);
                    createGaodeLog(logCode, logText, province, city, keyword, operateIp); //生成日志
                    List<MapMerchantInfo> poiListData = GdConfing.getGdMerchantInfoByApi(mapLogService, operateIp, logCode, province, city, search_area, location, keyword);
                    poiList.addAll(poiListData);
                    i++;
                    Thread.sleep(600);
                }
                //保存数据：存在则更新，不存在则更新
                if(!poiList.isEmpty()){
                    logText = "高德API接口调用>>>" + address + " 总数据量为：" + poiList.size();
                    logger.info(logText);
                    createGaodeLog(logCode, logText, province, city, keyword, operateIp); //生成日志
                    //获取历史数据
                    List<MapMerchantInfo> oldList = baseMapper.listAllEntity(params);
                    Map<String, MapMerchantInfo> oldDataIdMap = oldList.stream().collect(Collectors.toMap(e -> e.getDataId() + "", e->e, (key1, key2) -> key2));
                    Map<String, String> dataIdMap = new HashMap<>();
                    List<MapMerchantInfo> saveList = new ArrayList<>();
                    List<MapMerchantInfo> updateList = new ArrayList<>();
                    int total = 0;
                    for(MapMerchantInfo poi : poiList){
                        //去重
                        if(StringUtil.notNull(dataIdMap.get(poi.getDataId()))){
                            continue;
                        }
                        dataIdMap.put(poi.getDataId(), poi.getDataId());
                        MapMerchantInfo oldData = oldDataIdMap.get(poi.getDataId());
                        if(oldData == null){
                            saveList.add(poi);
                        }else{
                            oldData.setName(poi.getName());
                            oldData.setSearchArea(poi.getSearchArea());
                            oldData.setTel(poi.getTel());
                            oldData.setInfoUpdateTime(poi.getInfoUpdateTime());
                            oldData.setType(poi.getType());
                            oldData.preUpdateNoUser();
                            updateList.add(oldData);
                        }
                        if(saveList.size() == 800){
                            total += saveList.size();
                            logText = "高德API接口调用>>>执行数据新增：" + saveList.size() + "条，已新增总数：" + total + "条";
                            createGaodeLog(logCode, logText, province, city, keyword, operateIp); //生成日志
                            saveBatch(saveList);
                            saveList.clear();
                        }
                        if(updateList.size() == 800){
                            logText = "高德API接口调用>>>执行数据更新：" + updateList.size() + "条";
                            createGaodeLog(logCode, logText, province, city, keyword, operateIp); //生成日志
                            updateBatchById(updateList);
                            updateList.clear();
                        }
                    }
                    if(!saveList.isEmpty()){
                        total += saveList.size();
                        logText = "高德API接口调用>>>执行数据新增：" + saveList.size() + "条，已新增总数：" + total + "条";
                        createGaodeLog(logCode, logText, province, city, keyword, operateIp); //生成日志
                        saveBatch(saveList);
                    }
                    if(!updateList.isEmpty()){
                        logText = "高德API接口调用>>>执行数据更新：" + updateList.size() + "条";
                        createGaodeLog(logCode, logText, province, city, keyword, operateIp); //生成日志
                        updateBatchById(updateList);
                    }
                    logText = "高德API接口调用>>>" + address + " 去重并且排除已存在的数据，新增数据量为：" + total;
                    logger.info(logText);
                    createGaodeLog(logCode, logText, province, city, keyword, operateIp); //生成日志
                }
            }
            list = baseMapper.listAll(params);
        }
        return list;
    }

    /**
     * 生成高徳日志
     * @param logCode
     * @param logText
     * @param province
     * @param city
     * @param keywork
     * @param operateIp 操作IP
     */
    public void createGaodeLog(String logCode, String logText, String province, String city, String keywork, String operateIp){
        MapLog mapLog = mapLogService.createLogInfo(logCode, "gaode", "1", province, city, keywork, 0, 0, 0, logText, operateIp);
        mapLogService.save(mapLog);
    }

    /**
     * 省份/城市代码转中文
     * @param params
     * @return
     */
    public void chineseConvertMap(Map<String, Object> params){
        String provinceCode = params.get("province") + ""; // 省份
        String cityCode = params.get("city") + ""; // 城市
        //获取省份和城市中文名称
        if(StringUtil.notNull(provinceCode) && !"-1".equals(provinceCode)){
            MapDistrict provinceDistrict = mapDistrictService.getOne(new QueryWrapper<MapDistrict>().eq("level", "province").eq("adcode", provinceCode));
            if(ObjectUtil.isNotNull(provinceDistrict)){
                String province = provinceDistrict.getName(); // 省份中文名称
                params.put("province", province);
                if(provinceCode.equals(cityCode)){
                    params.put("city", province);
                }
            }
        }
        if(!provinceCode.equals(cityCode) && StringUtil.notNull(cityCode) && !"-1".equals(cityCode)){
            MapDistrict cityDistrict = mapDistrictService.getOne(new QueryWrapper<MapDistrict>().eq("level", "city").eq("adcode", cityCode));
            if(ObjectUtil.isNotNull(cityDistrict)){
                String city = cityDistrict.getName(); // 城市中文名称
                params.put("city", city);
            }
        }
    }

}
